﻿using System;
using System.Threading;
using System.ComponentModel;


	public static class DelegateExtensions
	{
		/// <summary>
		/// From BReusable
		/// </summary>
		/// <param name="actionToAsync"></param>
		/// <param name="finishedAction"></param>
		public static void RunAsync(this Action actionToAsync, Action<object, RunWorkerCompletedEventArgs> finishedAction)
		{
			var t = new BackgroundWorker();
			t.DoWork += (sender, e) => actionToAsync();
			t.RunWorkerCompleted += (sender, e) => finishedAction.Invoke(sender, e);//BackgroundWorkerFinished(sender, e);
			t.RunWorkerAsync();
		}
		/// <summary>
		/// From BReusable
		/// </summary>
		/// <param name="actionToAsync"></param>
		/// <returns></returns>
		public static Thread RunAsync(this Action actionToAsync)
		{
			var t = new Thread(new ThreadStart(actionToAsync));
			t.Start();
			return t;
		}

		/// <summary>
		/// From BReusable
		/// </summary>
		/// <param name="timedAction"></param>
		/// <param name="reportLead"></param>
		/// <param name="reporterAction"></param>
		public static void TimeAndReport(this Action timedAction, String reportLead, Action<String> reporterAction)
		{
			var s = new System.Diagnostics.Stopwatch();
			s.Start();
			timedAction();
			s.Stop();
			reporterAction(reportLead + " in " + s.WholePartOnly());
		}

		/// <summary>
		/// From BReusable
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="timedFunc"></param>
		/// <param name="reportLead"></param>
		/// <param name="reporterAction"></param>
		/// <returns></returns>
		public static T TimeAndReport<T>(this Func<T> timedFunc, String reportLead, Action<String> reporterAction)
		{
			T result;
			var s = new System.Diagnostics.Stopwatch();
			s.Start();
			result = timedFunc();
			s.Stop();
			reporterAction(reportLead + " in " + s.WholePartOnly());
			return result;
		}

		/// <summary>
		/// From BReusable
		/// </summary>
		/// <typeparam name="TResult"></typeparam>
		/// <param name="doWhat"></param>
		/// <returns></returns>
		public static BReusable.TryFunc<TResult> TryFunc<TResult>(this Func<TResult> doWhat)
		{
			return new BReusable.TryFunc<TResult>(doWhat);
		}

		/// <summary>
		/// From BReusable
		/// </summary>
		/// <typeparam name="TResult"></typeparam>
		/// <typeparam name="TException"></typeparam>
		/// <param name="doWhat"></param>
		/// <returns></returns>
		public static BReusable.TryFunc<TResult, TException> TryFunc<TResult, TException>(this Func<TResult> doWhat)
			where TException : Exception
		{
			return new BReusable.TryFunc<TResult, TException>(doWhat);
		}

		/// <summary>
		/// From BReusable
		/// </summary>
		/// <param name="doWhat"></param>
		/// <returns></returns>
		public static BReusable.TryAction Try(this Action doWhat)
		{
			return new BReusable.TryAction(doWhat);
		}

	}
